package com.netx.generics.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import com.netx.generics.basic.IntegrityException;
import com.netx.generics.time.Moment;


class ProtocolImplFile extends ProtocolImpl {

	private java.io.File _file;

	public ProtocolImplFile(Location base, String path) {
		super(base, path);
		_file = new java.io.File(base.getPhysicalPath(), this.path);
	}
	
	public String getPhysicalPath() {
		return base.getPhysicalPath() + getPath();
	}
	
	// This is quicker than the default impl:
	public String getName() {
		return _file.getName();
	}
	
	public boolean exists() throws IOException {
		return _file.exists();
	}
	
	public boolean isFile() throws IOException {
		return _file.isFile();
	}

	public boolean isDirectory() throws IOException {
		return _file.isDirectory();
	}
	
	public boolean canRead() throws IOException {
		return _file.canRead();
	}

	public boolean canWrite() throws IOException {
		return _file.canWrite();
	}

	public boolean isHidden() throws IOException {
		return _file.isHidden();
	}

	public void setReadOnly() throws IOException {
		_file.setReadOnly();
	}

	public Moment getLastModified() {
		return new Moment(_file.lastModified());
	}

	public void setLastModified(Moment moment) throws IOException {
		_file.setLastModified(moment.getTimeInMilliseconds());
	}

	public long getSize() throws IOException {
		 return _file.length();
	}

	public void renameTo(String name) throws IOException {
		if(name.startsWith("/")) {
			_file.renameTo(new java.io.File(base.getPhysicalPath(), name));
		}
		else {
			_file.renameTo(new java.io.File(getPhysicalPath(), name));
		}
	}

	public String[] list() throws IOException {
		return _file.list();
	}

	public boolean mkdirs() throws IOException {
		return _file.mkdirs();
	}

	public boolean createNewFile() throws IOException {
		return _file.createNewFile();
	}

	public boolean delete() throws IOException {
		return _file.delete();
	}

	public void deleteOnExit() throws IOException {
		_file.deleteOnExit();
	}

	public URI toURI() {
		return _file.toURI();
	}

	public URL toURL() {
		try {
			return toURI().toURL();
		}
		catch(MalformedURLException mue) {
			throw new IntegrityException(mue);
		}
	}
	
	public InputStream getInputStream() throws IOException {
		return new FileInputStream(_file);
	}

	public OutputStream getOutputStream(boolean append) throws IOException {
		return new FileOutputStream(_file, append);
	}
	
	public IOException translate(IOException io, String path) {
		//TODO many, many more exceptions:
		if(io instanceof FileNotFoundException) {
			if(io.getMessage().contains("(The process cannot access the file because it is being used by another process)")) {
				return new FileLockedException("'"+path+"': file is locked and cannot be accessed");
			}
			else {
				return io;
			}
		}
		else {
			return new UnknownIOException("'"+path+"': "+io);
		}
	}
	
	public IOException translate(RuntimeException re, String path) {
		if(re instanceof SecurityException) {
			return new AccessDeniedException("'"+path+"': "+re.getMessage());
		}
		else {
			throw re;
		}
	}
}
